package service

import (
	"chat/common"
	utils "chat/util"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"net/http"
	"strconv"
)

type UserService struct {
	common.AllCommonStruct
	Nick        string `gorm:"notnull;unique;size:16;comment:用户昵称;" json:"nick"`
	UserPic     string `gorm:"notnull;size:200;comment:用户头像" json:"userPic"`
	Account     string `gorm:"notnull;unique;size:50;comment:用户账号;" json:"account"`
	Pwd         string `gorm:"->:false;notnull;size:50;comment:用户密码" json:"pwd"`
	Email       string `gorm:"notnull;unique;size:50;comment:用户邮箱" json:"email"`
	Sign        string `gorm:"default:这个人很懒，什么都没有写~;size:100;comment:用户签名" json:"sign"`
	LoginAt     string `gorm:"size:50;notnull;comment:用户登录IP" json:"loginAt"`
	LoginAtName string `gorm:"size:50;comment:用户登录区域名称" json:"loginAtName"`
	RoomNo      uint32 `gorm:"size:12;comment:用户房间号" json:"roomNo"`
	RoomPwd     string `gorm:"size:16;comment:房间密码" json:"roomPwd"`
	RoomName    string `gorm:"size:100;comment:房间标题" json:"roomName"`
	SocketSign  string `gorm:"notnull;size:50;comment:用户socketSign" json:"socketSign"`
	Token       string `gorm:"-" json:"token"`
}
type userRegister struct {
	common.AllCommonStruct
	Nick        string `binding:"required" json:"nick"`
	UserPic     string `binding:"required" json:"userPic"`
	Account     string `binding:"required" json:"account"`
	Pwd         string `binding:"required" json:"pwd"`
	Email       string `binding:"required" json:"email"`
	SocketSign  string `json:"socketSign"`
	LoginAt     string `json:"loginAt"`
	LoginAtName string `json:"loginAtName"`
}

type userLogin struct {
	Account     string `binding:"required" json:"account"`
	Pwd         string `binding:"required" json:"pwd"`
	LoginAt     string `json:"loginAt"`
	LoginAtName string `json:"loginAtName"`
}
type userUpdate struct {
	Id       int    `json:"id"`
	RoomName string `json:"roomName"`
	Nick     string `json:"nick"`
	Sign     string `json:"sign"`
	UserPic  string `json:"userPic"`
}

func (user *UserService) TableName() string {
	return "user"
}

var aes utils.AES = utils.AES{
	Data: "",
	Key:  common.SECRET,
}

type RoomInfo struct {
	RoomNo   uint32 `json:"roomNo"`
	RoomName string `json:"roomName"`
	Nick     string `json:"nick"`
	RoomPwd  string `json:"roomPwd"`
	UserPic  string `json:"userPic"`
	Sign     string `json:"sign"`
}

func (user *UserService) Register(ctx *gin.Context, db *gorm.DB) {
	//var model UserService
	aes.Data = fmt.Sprintf("%d:%s", user.Id, user.Account)
	var register userRegister
	if bindErr := ctx.ShouldBindJSON(&register); bindErr != nil {
		utils.Result(http.StatusBadRequest, "参数错误", ctx)
		return
	}
	account := db.Table(user.TableName()).Where("account=?", register.Account)
	if account.RowsAffected > 0 {
		utils.Result(http.StatusBadRequest, "账号已存在", ctx)
		return
	}
	email := db.Table(user.TableName()).Where("email=?", register.Email)
	if email.RowsAffected > 0 {
		utils.Result(http.StatusBadRequest, "邮箱已存在", ctx)
		return
	}
	register.LoginAt = ctx.RemoteIP()
	register.LoginAtName = ""
	encrypt, err := aes.AESEncrypt()
	if err != nil {
		utils.Result(http.StatusBadRequest, nil, ctx)
		return
	}
	register.SocketSign = encrypt
	register.Pwd = utils.Md5Crypto(register.Pwd)
	rows := db.Table(user.TableName()).Create(&register)
	if rows.RowsAffected > 0 {
		utils.Result(http.StatusOK, nil, ctx)
	} else {
		utils.Result(http.StatusBadRequest, nil, ctx)
	}
}
func (user *UserService) Login(ctx *gin.Context, db *gorm.DB) {
	var model UserService
	var login userLogin
	var claims utils.Claims
	aes.Data = fmt.Sprintf("%d:%s", user.Id, user.Account)
	if bindErr := ctx.ShouldBindJSON(&login); bindErr != nil {
		fmt.Println(bindErr)
		utils.Result(http.StatusBadRequest, "参数错误", ctx)
		return
	}
	login.LoginAt = ctx.RemoteIP()
	login.LoginAtName = ""
	rows := db.Debug().Table(user.TableName()).Where("(account = ? OR email = ?) AND pwd = ?", login.Account, login.Account, utils.Md5Crypto(login.Pwd)).Find(&model)
	token, err := claims.GenerateToken(model)
	if err != nil {
		utils.Result(http.StatusBadRequest, "token生成失败", ctx)
		return
	}
	model.Token = token
	if rows.RowsAffected > 0 {
		utils.Result(http.StatusOK, model, ctx)
	} else {
		utils.Result(http.StatusBadRequest, "用户未找到", ctx)
	}
}
func (user *UserService) UpdateUser(ctx *gin.Context, db *gorm.DB) {
	var u userUpdate
	if bindErr := ctx.ShouldBindJSON(&u); bindErr != nil {
		utils.Result(http.StatusBadRequest, nil, ctx)
		return
	}
	err := db.Table(user.TableName()).Where("id = ?", u.Id).Select("user_pic", "sign", "nick", "room_name").Updates(&u).Error
	if err != nil {
		utils.Result(http.StatusBadRequest, err.Error(), ctx)
		return
	}
	utils.Result(http.StatusOK, nil, ctx)
}
func (user *UserService) GetRoomInfo(ctx *gin.Context, db *gorm.DB) {
	var room RoomInfo
	roomNo, ok := ctx.GetQuery("roomNo")
	if !ok {
		utils.Result(http.StatusBadRequest, nil, ctx)
		return
	}
	atoi, err := strconv.Atoi(roomNo)
	if err != nil {
		utils.Result(http.StatusBadRequest, nil, ctx)
		return
	}
	queryErr := db.Table(user.TableName()).Where("room_no = ?", atoi).Find(&room).Error
	if queryErr != nil {
		utils.Result(http.StatusBadRequest, nil, ctx)
		return
	}
	utils.Result(http.StatusOK, room, ctx)
}
func (user *UserService) GetRoomList(ctx *gin.Context, db *gorm.DB) {
	var roomList []RoomInfo
	err := db.Table(user.TableName()).Where("room_no > 0").Find(&roomList).Error
	if err != nil {
		utils.Result(http.StatusBadRequest, nil, ctx)
		return
	}
	utils.Result(http.StatusOK, roomList, ctx)
}
